package com.salts.service.Impl;

import com.salts.Dao.*;
import com.salts.domain.dto.ClothCategoryColorSizeDto;
import com.salts.domain.dto.ClothDto;
import com.salts.domain.dto.ColorDto;
import com.salts.domain.dto.SizeDto;
import com.salts.domain.po.*;
import com.salts.domain.vo.*;
import com.salts.service.HomePageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

import static com.salts.util.ReadPic.readImges;

@Service
public class HomePageServiceServiceImpl implements HomePageService {
    @Autowired
    ClothMapper clothMapper;
    @Autowired
    OrderInfoMapper orderInfoMapper;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    ComboMapper comboMapper;
    @Autowired
    ComboDetailMapper comboDetailMapper;
    @Autowired
    StockMapper stockMapper;
    @Autowired
    ColorMapper colorMapper;
    @Autowired
    SizeMapper sizeMapper;
    @Autowired
    CategoryMapper categoryMapper;

    @Override
    public List<CastVo> wheelCast() {
        List<CastVo> castVos=new ArrayList<>();
        String directoryPath="src/main/resources/static/weelCastPic";
        File directory = new File(directoryPath);
        if (directory.isDirectory()) {
            Map<String, String> imgUrls= new HashMap<>();
            imgUrls = readImges(directory,imgUrls);
            for (Map.Entry<String, String> entry : imgUrls.entrySet()) {
                CastVo castVo = new CastVo();
                castVo.setName(entry.getKey());
                castVo.setImageUrl(entry.getValue());
                castVos.add(castVo);
            }
            return castVos;
        }
        System.out.println("指定的路径不是一个目录。");
        return null;
    }

    @Override
    public String recommendedProduct() throws IOException {
        // 读取静态 JSON 文件内容
        ClassPathResource resource = new ClassPathResource("static/recommend/recommend.json");
        byte[] bytes = StreamUtils.copyToByteArray(resource.getInputStream());
        String jsonContent = new String(bytes, StandardCharsets.UTF_8);
        return jsonContent;
    }
//结合内容推荐算法
    @Override
    public List<DisplayClothVo> hotProduct(Integer userId) {
        //如果没有注册过的用户
        if (userId.equals(null)){
            List<Integer> top5ProductIds = orderDetailMapper.getTop5ProductIds();
            //clothMapper.getProductInfoById(top10ProductIds);
            //return clothMapper.getProductInfoById(top5ProductIds);
            return this.recommendedProject(top5ProductIds);
        }else {//已登录用户
            List<ClothCategoryColorSizeDto> allClothInfo = getAllClothInfo();
            List<OrderDetail> orderDetails=orderDetailMapper.getUserOrderDetailInfo(userId);
            List<Integer> userCloths = orderDetails.stream().map(OrderDetail::getClothId).distinct().collect(Collectors.toList());
            // 获取用户已购买服装的特征向量列表
            List<double[]> userClothFeatures = new ArrayList<>();
            for (Integer clothId : userCloths) {
                // 根据 clothId 从 allClothInfo 中获取对应的服装特征向量，并加入列表中
                ClothCategoryColorSizeDto clothInfo = getClothInfoById(allClothInfo, clothId);
                if (clothInfo != null) {
                    double[] clothFeatures = extractFeatures(clothInfo);
                    userClothFeatures.add(clothFeatures);
                }
            }
            // 遍历所有服装信息，计算其与用户已购买服装的相似度
            Map<Integer, Double> clothSimilarityMap = new HashMap<>();
            for (ClothCategoryColorSizeDto clothInfo : allClothInfo) {
                // 提取当前服装的特征向量
                double[] currentClothFeatures = extractFeatures(clothInfo);

                // 计算当前服装与用户已购买服装列表中所有服装的平均相似度
                double totalSimilarity = 0.0;
                for (double[] userClothFeaturess : userClothFeatures) {
                    double similarity = calculateEuclideanDistance(userClothFeaturess, currentClothFeatures);
                    totalSimilarity += similarity;
                }
                double averageSimilarity = totalSimilarity / userClothFeatures.size();

                // 将当前服装的平均相似度加入到相似度映射中
                clothSimilarityMap.put(clothInfo.getClothId(), averageSimilarity);
            }
            // 根据相似度映射对服装进行排序，取相似度最高的若干件服装作为推荐结果
            List<Integer> recommendedClothIds = clothSimilarityMap.entrySet().stream()
                    .sorted(Map.Entry.comparingByValue())
                    .limit(15)
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
            //查询到对应的服装信息并返回
            List<DisplayClothVo> returnList=clothMapper.getProductInfoById(recommendedClothIds);
            return returnList;
        }

    }
    List<DisplayClothVo> recommendedProject(List<Integer> userCloths){
        List<ClothCategoryColorSizeDto> allClothInfo = getAllClothInfo();
        // 获取用户已购买服装的特征向量列表
        List<double[]> userClothFeatures = new ArrayList<>();
        for (Integer clothId : userCloths) {
            // 根据 clothId 从 allClothInfo 中获取对应的服装特征向量，并加入列表中
            ClothCategoryColorSizeDto clothInfo = getClothInfoById(allClothInfo, clothId);
            if (clothInfo != null) {
                double[] clothFeatures = extractFeatures(clothInfo);
                userClothFeatures.add(clothFeatures);
            }
        }
        // 遍历所有服装信息，计算其与用户已购买服装的相似度
        Map<Integer, Double> clothSimilarityMap = new HashMap<>();
        for (ClothCategoryColorSizeDto clothInfo : allClothInfo) {
            // 提取当前服装的特征向量
            double[] currentClothFeatures = extractFeatures(clothInfo);

            // 计算当前服装与用户已购买服装列表中所有服装的平均相似度
            double totalSimilarity = 0.0;
            for (double[] userClothFeaturess : userClothFeatures) {
                double similarity = calculateEuclideanDistance(userClothFeaturess, currentClothFeatures);
                totalSimilarity += similarity;
            }
            double averageSimilarity = totalSimilarity / userClothFeatures.size();

            // 将当前服装的平均相似度加入到相似度映射中
            clothSimilarityMap.put(clothInfo.getClothId(), averageSimilarity);
        }
        // 根据相似度映射对服装进行排序，取相似度最高的若干件服装作为推荐结果
        List<Integer> recommendedClothIds = clothSimilarityMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .limit(15)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        //查询到对应的服装信息并返回
        List<DisplayClothVo> returnList=clothMapper.getProductInfoById(recommendedClothIds);
        return returnList;
    }

    private ClothCategoryColorSizeDto getClothInfoById(List<ClothCategoryColorSizeDto> allClothInfo, Integer clothId) {
        if (allClothInfo.isEmpty()){
            return null;
        }
        Optional<ClothCategoryColorSizeDto> clothInfoOptional = allClothInfo.stream().filter(cloth -> cloth.getClothId().equals(clothId)).findFirst();
        if (clothInfoOptional.isPresent()) {
            return clothInfoOptional.get();
        } else {
            return null;
        }
    }

    public List<ClothCategoryColorSizeDto> getAllClothInfo(){
        List<DisplayCategoryVo> categoryAllInfo = categoryMapper.getCategoryAllInfo();
        List<ClothDto> stocks=stockMapper.getAllInfo();
        List<ClothCategoryColorSizeDto> coth=new ArrayList<>();
        // 遍历分类信息
        for (DisplayCategoryVo displayCategoryVo : categoryAllInfo) {
            String categoryOne = displayCategoryVo.getCategoryOne();
            String categoryTwo = displayCategoryVo.getCategoryTwo();
            String categoryTre = displayCategoryVo.getCategoryTre();
            List<Integer> clothIds=categoryMapper.getClothIds(categoryOne,categoryTwo,categoryTre);
            // 遍历每个分类的衣物ID
            for (Integer clothId : clothIds) {
                // 在已有的衣物列表中查找对应的衣物信息
                ClothDto cloth = findClothById(stocks, clothId);
                if (cloth != null) {
                    // 创建 ClothCategoryColorSizeDto 对象，并设置衣物、颜色、尺寸和分类信息
                    ClothCategoryColorSizeDto dto = new ClothCategoryColorSizeDto();
                    dto.setClothId(cloth.getClothId());
                    dto.setColorId(cloth.getColorId());
                    dto.setSpecId(cloth.getSpecId());
                    dto.setCategoryOne(categoryOne);
                    dto.setCategoryTwo(categoryTwo);
                    dto.setCategoryTre(categoryTre);
                    // 将对象添加到列表中
                    coth.add(dto);
                }
            }
        }
        return coth;
    }

    private double[] extractFeatures(ClothCategoryColorSizeDto clothDto) {
        // 创建特征向量，这里假设颜色、尺寸和分类分别用整数表示
        double[] featureVector = new double[3];
        featureVector[0] = clothDto.getColorId(); // 颜色特征
        featureVector[1] = clothDto.getSpecId();  // 尺寸特征
        featureVector[2] = getCategoryVector(clothDto.getCategoryOne(), clothDto.getCategoryTwo(), clothDto.getCategoryTre()); // 分类特征
        return featureVector;
    }

    // 将分类特征转换为数值化的特征向量
    private double getCategoryVector(String categoryOne, String categoryTwo, String categoryTre) {
        // 这里可以根据分类的不同取值转换为不同的数值，例如使用独热编码
        // 简单起见，这里只是将分类的字符串拼接并转换为哈希码作为特征向量
        String categoryString = categoryOne + "-" + categoryTwo + "-" + categoryTre;
        return categoryString.hashCode();
    }
    //欧氏距离公式的代码实现
    private double calculateEuclideanDistance(double[] featureVector1, double[] featureVector2) {
        double sum = 0.0;
        for (int i = 0; i < featureVector1.length; i++) {
            sum += Math.pow(featureVector1[i] - featureVector2[i], 2);
        }
        return Math.sqrt(sum);
    }
    private List<Integer> recommendClothsBasedOnContent(List<ClothCategoryColorSizeDto> allClothInfo, List<Integer> userCloths) {
        List<Integer> recommendedClothIds = new ArrayList<>();

        // 这里简单起见，假设推荐与用户购买过的服装类别相同的其他服装
        for (ClothCategoryColorSizeDto clothInfo : allClothInfo) {
            if (!userCloths.contains(clothInfo.getClothId())) {
                // 如果该服装不在用户已购买的服装列表中，则将其加入推荐列表
                recommendedClothIds.add(clothInfo.getClothId());
            }
        }

        // 这里可以根据更复杂的推荐算法进行进一步的处理，例如根据服装的颜色、尺寸等特征计算相似度进行推荐
        // 也可以根据用户历史购买记录进行个性化推荐

        return recommendedClothIds;
    }


    // 根据衣物ID在已有的衣物列表中查找对应的衣物信息
    private ClothDto findClothById(List<ClothDto> cloths, Integer clothId) {

        for (ClothDto cloth : cloths) {
            if (cloth.getClothId().equals(clothId)){
                return cloth;
            };
        }
            return null;
    }
//1.搜索出对应商品的尺寸和颜色，返回回来 2.根据参数直接查询stock
    @Override
    public ClothVo productDetail(int clothId) {
        if (clothId==0){
            return null;
        }
        Cloth productInfo = clothMapper.getProductInfo(clothId);
        List<ClothVo> clothVos = new ArrayList<>();
        List<SizeDto> sizeDtos=stockMapper.selectSize(clothId);
        List<ColorDto> colorDtos = stockMapper.selectColor(clothId);
        ClothVo clothVo = new ClothVo();
        clothVo.setClothId(productInfo.getId());
        clothVo.setClothName(productInfo.getClothName());
        clothVo.setState(productInfo.getState());
        clothVo.setBrand(productInfo.getBrand());
        clothVo.setComment(productInfo.getComment());
        clothVo.setPricePrimitive(productInfo.getPrice());
        clothVo.setPriceNew(productInfo.getPrice());
        clothVo.setColors(colorDtos);
        clothVo.setSpecs(sizeDtos);
        clothVo.setImgUrl(productInfo.getImageUrl());
        return clothVo;
    }

    @Override
    public Integer stockNumberQuery(ClothDto clothDto) {
        Integer stock = stockMapper.queryStock(clothDto);
        return stock;
    }


    @Override
    public List<DisplayClothVo> newProductDisplay() {
        return clothMapper.getNewProduct();
    }

    @Override
    public List<DisplayComboVo> promotionalProduct() {
        List<DisplayComboVo> displayComboVos = comboMapper.newComboInfo();
        return displayComboVos;
    }

    @Override
    public List<DisplayComboVo> promotionalFullInfo() {
        return comboMapper.fullComboInfo();
    }

    @Override
    public ComboVo promotionalDetail(int comboId) {
        ComboVo comboVo = new ComboVo();
        Combo combo = comboMapper.queryComboInfo(comboId);
        List<ComboDetail> comboDetails = comboDetailMapper.queryComboDetail(comboId);
        comboVo.setCombo(combo);
        comboVo.setComboDetails(comboDetails);
        return comboVo;
    }

    @Override
    public List<DisplayClothVo> categoryProduct() {
        //先不做咯
        return null;
    }

    @Override
    public List<DisplayClothVo> brandProductDisplay() {
        //先不实现
        return null;
    }
}
